<template>
  <h4>按住空白区域可拖拽，鼠标滚轮缩放。仅作参考，使用时可参考示例代码</h4>
  <b style="color:red">注意：</b>
  在开发过程中如果需要使用缩放/拖拽功能，需要将 canvas 元素设置 position: absolute ，并将 canvas 父级元素设置成 position: relative , 详见示例代码
  <h4 style="color:red">当需要拖拽画布且需要绘制图案时，绘制过程中请注意处理拖拽事件，防止在绘制图案的过程中画布产生位移</h4>
  <el-button @click="drawNode('rect')">绘制矩形</el-button>
  <hr>

  <div id='board'>
    <canvas
      id='drawingBoard'
      class="shadow"
    ></canvas>
  </div>

</template>

<script setup>
import { init, setNode } from "@/home/common.js";
import { onMounted, ref } from "vue";

const width = 1400;
const height = 1000;
const defaultStyle = {
  lineWidth: 5,
};

let draw = null;
onMounted(() => {
  draw = init({ width, height, defaultStyle });
  draw.addNode({
    type: "circular",
    drag: true,
    x: 100,
    y: 240,
    radiusX: 50,
    radiusY: 30,
    level: 1,
    textInfo: {
      text: "可拖拽",
    },
  });
  draw.addNode({
    type: "circular",
    drag: false,
    x: 500,
    y: 200,
    radiusX: 50,
    radiusY: 30,
    level: 1,
    textInfo: {
      text: "不可拖拽",
    },
  });

  listenerDragScale();
  listenerDragPosition();
});

// 添加图案
const drawing = ref(false);
const drawNode = () => {
  setNode("rect");
  drawing.value = true;
};

// 缩放控制
const listenerDragScale = () => {
  let scale = ref(1);
  let dom = document.getElementById("drawingBoard");
  document.getElementById("board").addEventListener("mousewheel", (val) => {
    setTimeout(() => {
      if (val.wheelDelta > 0) {
        // 放大
        scale.value += 0.01;
      } else {
        scale.value -= 0.01;
        if (scale.value < 0.5) scale.value = 0.5;
      }
      dom.style.transform = `scale(${scale.value})`;
    }, 10);
  });
};

// 拖拽控制
const listenerDragPosition = () => {
  let drag = ref(false);
  let dom = document.getElementById("drawingBoard");

  let startX = ref(0); // 记录每次鼠标点击的初始位置
  let startY = ref(0);

  let tagX = ref(0); // 暂存区，记录每次拖拽产生的 x/y 方向上的变化
  let tagY = ref(0);

  let posX = ref(0); // 记录画布实际移动的位置
  let posY = ref(0);

  /* 
    ｜- 第一种方式，通过 client 计算位置 
    ｜- 推荐: 可以直接监听画布父级的事件，由于 client 是参考当前显示屏左上角，所以不用担心 dom 移动带来的问题
    ｜- * 需要注意：要注意在选中图案时禁止拖拽，否则会导致图案和画布的拖拽冲突
  */

  document.getElementById("board").addEventListener("mousedown", (val) => {
    tagX.value = 0;
    tagY.value = 0;
    let node = draw.getNode();
    if (JSON.stringify(node) === "{}" && !drawing.value) {
      // 选中图案时禁止拖拽（会和图案的拖拽冲突）
      drag.value = true;
      startX.value = val.clientX;
      startY.value = val.clientY;
    }
  });

  document.getElementById("board").addEventListener("mouseup", () => {
    posX.value += tagX.value;
    posY.value += tagY.value;
    drag.value = false;
    dom.style.left = posX.value + "px";
    dom.style.top = posY.value + "px";

    drawing.value = false;
    setNode(null);
  });

  document.getElementById("board").addEventListener("mousemove", (val) => {
    if (drag.value) {
      let subX = val.clientX - startX.value;
      let subY = val.clientY - startY.value;

      tagX.value = subX;
      tagY.value = subY;

      dom.style.left = tagX.value + posX.value + "px";
      dom.style.top = tagY.value + posY.value + "px";
    }
  });

  /* -------------------------------------- 分割线 -------------------------------------- */

  /* 
    ｜- 第二种方式，通过 offset 计算位置 
    ｜- 不推荐: 由于使用 offset ，为了不产生移动的问题，需要将鼠标移动的监听放在画布上而不是画布父级，超出画布显示区域外的地方无法进行拖拽操作 （ 这将意味着当使用多张画布合成一张作展示的情况下要分别去改变多张画布的样式 ） 
    ｜- * 需要注意：要注意在选中图案时禁止拖拽，否则会导致图案和画布的拖拽冲突
  */

  /*
    document.getElementById("board").addEventListener("mousedown", (val) => {
      drag.value = true;
      startX.value = val.offsetX;
      startY.value = val.offsetY;
    });

    document.getElementById("board").addEventListener("mouseup", () => {
      startX.value = 0;
      startY.value = 0;
      drag.value = false;
    });

    document.getElementById("drawingBoard").addEventListener("mousemove", (val) => {
      if (drag.value) {
        let subX = val.offsetX - startX.value;
        let subY = val.offsetY - startY.value;
        posX.value += subX;
        posY.value += subY;
        dom.style.left = posX.value + "px";
        dom.style.top = posY.value + "px";
      }
    });
  */
};
</script>

<style scoped>
#board {
  overflow: hidden;
  position: relative;
  width: 100%;
  height: 600px;
  margin-top: 20px;
  background: rgb(245, 245, 245);
  box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.2);
}
#drawingBoard {
  position: absolute;
  left: 0px;
  top: 0px;
}
</style>